ποΈGitΠ―ΡΠ°ποΈ
feature/settings/settings-validation.md 4d4070c8e1ed73a56ee2f054300a0f62e3fe2e62 (4d4070c8) Text, 26.83 KB
Tc9d1d9# Settings Screen Validation Reference
This document describes the validation rules enforced on each radio configuration and module
configuration settings screen. Constraints are sourced from two layers:
Tff7b721. **Protobuf schema** β field types, enums, and Ta5d6ff`max_size` annotations defined in the
Ta5d6ff`meshtastic/protobufs` submodule.
Tff7b722. **UI form layer** β additional range checks, conditional visibility, and interval pickers
implemented in Ta5d6ff`feature/settings/src/commonMain/.../radio/component/`.
Tff7b72> **Reusable components** live in `core/ui/.../component/`. Each component enforces its own
Tff7b72> validation strategy (see [UI Component Validation](#ui-component-validation) at the bottom).
---
Tc9d1d9## Table of Contents
Tff7b72- [Tff7b72Device Config Screens](Te6edf3#device-config-screens)
Tff7b72- [Tff7b72User](Te6edf3#user-configuserconfig)
Tff7b72- [Tff7b72Device](Te6edf3#device-configdeviceconfig)
Tff7b72- [Tff7b72Position](Te6edf3#position-configpositionconfig)
Tff7b72- [Tff7b72Power](Te6edf3#power-configpowerconfig)
Tff7b72- [Tff7b72Network](Te6edf3#network-confignetworkconfig)
Tff7b72- [Tff7b72Display](Te6edf3#display-configdisplayconfig)
Tff7b72- [Tff7b72LoRa](Te6edf3#lora-configloraconfig)
Tff7b72- [Tff7b72Bluetooth](Te6edf3#bluetooth-configbluetoothconfig)
Tff7b72- [Tff7b72Security](Te6edf3#security-configsecurityconfig)
Tff7b72- [Tff7b72Module Config Screens](Te6edf3#module-config-screens)
Tff7b72- [Tff7b72MQTT](Te6edf3#mqtt-moduleconfigmqttconfig)
Tff7b72- [Tff7b72Serial](Te6edf3#serial-moduleconfigserialconfig)
Tff7b72- [Tff7b72External Notification](Te6edf3#external-notification-moduleconfigexternalnotificationconfig)
Tff7b72- [Tff7b72Store & Forward](Te6edf3#store--forward-moduleconfigstoreforwardconfig)
Tff7b72- [Tff7b72Range Test](Te6edf3#range-test-moduleconfigrangetestconfig)
Tff7b72- [Tff7b72Telemetry](Te6edf3#telemetry-moduleconfigtelemetryconfig)
Tff7b72- [Tff7b72Canned Message](Te6edf3#canned-message-moduleconfigcannedmessageconfig)
Tff7b72- [Tff7b72Audio](Te6edf3#audio-moduleconfigaudioconfig)
Tff7b72- [Tff7b72Remote Hardware](Te6edf3#remote-hardware-moduleconfigremotehardwareconfig)
Tff7b72- [Tff7b72Neighbor Info](Te6edf3#neighbor-info-moduleconfigneighborinfoconfig)
Tff7b72- [Tff7b72Ambient Lighting](Te6edf3#ambient-lighting-moduleconfigambientlightingconfig)
Tff7b72- [Tff7b72Detection Sensor](Te6edf3#detection-sensor-moduleconfigdetectionsensorconfig)
Tff7b72- [Tff7b72Paxcounter](Te6edf3#paxcounter-moduleconfigpaxcounterconfig)
Tff7b72- [Tff7b72Status Message](Te6edf3#status-message-moduleconfigstatusmessageconfig)
Tff7b72- [Tff7b72Traffic Management](Te6edf3#traffic-management-moduleconfigtrafficmanagementconfig)
Tff7b72- [Tff7b72TAK](Te6edf3#tak-moduleconfigtakconfig)
Tff7b72- [Tff7b72Mesh Beacon](Te6edf3#mesh-beacon-moduleconfigmeshbeaconconfig)
Tff7b72- [Tff7b72Channel Config](Te6edf3#channel-config)
Tff7b72- [Tff7b72Interval Configurations](Te6edf3#interval-configurations)
Tff7b72- [Tff7b72UI Component Validation](Te6edf3#ui-component-validation)
---
Tc9d1d9## Device Config Screens
Tc9d1d9### User (`Config.UserConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`long_name` | String | maxSize: 39 bytes (proto max_size: 40) | Required (non-blank) |
| Ta5d6ff`short_name` | String | maxSize: 4 bytes (proto max_size: 5) | Required (non-blank) |
| Ta5d6ff`is_licensed` | Boolean | Toggle | β |
| Ta5d6ff`is_unmessagable` | Boolean | Toggle | Enabled only when device capability Ta5d6ff`canToggleUnmessageable` is true or role is unmessageable |
Tc9d1d9### Device (`Config.DeviceConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`role` | Enum | Dropdown: Ta5d6ff`DeviceConfig.Role` entries | Router/ROUTER_LATE/REPEATER roles trigger a confirmation dialog |
| Ta5d6ff`rebroadcast_mode` | Enum | Dropdown: Ta5d6ff`RebroadcastMode` entries | ALL, ALL_SKIP_DECODING, LOCAL_ONLY, KNOWN_ONLY, NONE, CORE_PORTNUMS_ONLY |
| Ta5d6ff`node_info_broadcast_secs` | Interval | Dropdown: Ta5d6ff`NODE_INFO_BROADCAST` intervals | See [Tff7b72Interval Configurations](Te6edf3#interval-configurations) |
| Ta5d6ff`double_tap_as_button_press` | Boolean | Toggle | β |
| Ta5d6ff`disable_triple_click` | Boolean | Toggle (inverted) | UI shows "enabled" when proto field is Ta5d6ff`false` |
| Ta5d6ff`led_heartbeat_disabled` | Boolean | Toggle (inverted) | UI shows "enabled" when proto field is Ta5d6ff`false` |
| Ta5d6ff`tzdef` | String | maxSize: 64 bytes (proto max_size: 65) | Clearable |
| Ta5d6ff`button_gpio` | Integer | Numeric input | β |
| Ta5d6ff`buzzer_gpio` | Integer | Numeric input | β |
Tc9d1d9### Position (`Config.PositionConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`position_broadcast_secs` | Interval | Dropdown: Ta5d6ff`POSITION_BROADCAST` intervals | β |
| Ta5d6ff`position_broadcast_smart_enabled` | Boolean | Toggle | Controls visibility of smart broadcast fields |
| Ta5d6ff`broadcast_smart_minimum_interval_secs` | Interval | Dropdown: Ta5d6ff`SMART_BROADCAST_MINIMUM` intervals | Visible only when smart broadcast enabled |
| Ta5d6ff`broadcast_smart_minimum_distance` | Integer | Numeric input | Visible only when smart broadcast enabled |
| Ta5d6ff`fixed_position` | Boolean | Toggle | Controls visibility of lat/lon/alt vs GPS fields |
| Ta5d6ff`latitude` | Double | Range: β90.0 to +90.0 | Visible only when Ta5d6ff`fixed_position = true` |
| Ta5d6ff`longitude` | Double | Range: β180.0 to +180.0 | Visible only when Ta5d6ff`fixed_position = true` |
| Ta5d6ff`altitude` | Integer | Numeric input | Visible only when Ta5d6ff`fixed_position = true` |
| Ta5d6ff`gps_mode` | Enum | Dropdown: Ta5d6ff`GpsMode` entries | Visible only when Ta5d6ff`fixed_position = false` |
| Ta5d6ff`gps_update_interval` | Interval | Dropdown: Ta5d6ff`GPS_UPDATE` intervals | Visible only when Ta5d6ff`fixed_position = false` |
| Ta5d6ff`position_flags` | Bitwise | Checkbox set: Ta5d6ff`PositionFlags` entries (excl. UNSET) | Bitwise OR of selected flags |
| Ta5d6ff`rx_gpio` | Integer | Dropdown: GPIO pins 0β48 | β |
| Ta5d6ff`tx_gpio` | Integer | Dropdown: GPIO pins 0β48 | β |
| Ta5d6ff`gps_en_gpio` | Integer | Dropdown: GPIO pins 0β48 | β |
Tc9d1d9### Power (`Config.PowerConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`is_power_saving` | Boolean | Toggle | β |
| Ta5d6ff`on_battery_shutdown_after_secs` | Interval | Dropdown: Ta5d6ff`ALL` intervals | β |
| Ta5d6ff`adc_multiplier_override` | Float | Must be > 0.0 when enabled | Checkbox + float input; float visible only when enabled |
| Ta5d6ff`wait_bluetooth_secs` | Interval | Dropdown: Ta5d6ff`NAG_TIMEOUT` intervals | 0sβ60s |
| Ta5d6ff`sds_secs` | Interval | Dropdown: Ta5d6ff`ALL` intervals | β |
| Ta5d6ff`min_wake_secs` | Interval | Dropdown: Ta5d6ff`NAG_TIMEOUT` intervals | 0sβ60s |
| Ta5d6ff`device_battery_ina_address` | Integer | Numeric input (I2C address) | β |
Tc9d1d9### Network (`Config.NetworkConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`wifi_enabled` | Boolean | Toggle | Controls visibility of Wi-Fi fields |
| Ta5d6ff`wifi_ssid` | String | maxSize: 32 bytes (proto max_size: 33) | Visible when Ta5d6ff`wifi_enabled = true` |
| Ta5d6ff`wifi_psk` | Password | maxSize: 64 bytes (proto max_size: 65) | Visible when Ta5d6ff`wifi_enabled = true` |
| Ta5d6ff`eth_enabled` | Boolean | Toggle | Visible only when device Ta5d6ff`hasEthernet = true` |
| Ta5d6ff`ntp_server` | String | maxSize: 32 bytes (proto max_size: 33) | β |
| Ta5d6ff`rsyslog_server` | String | maxSize: 32 bytes (proto max_size: 33) | β |
| Ta5d6ff`address_mode` | Enum | Dropdown: Ta5d6ff`AddressMode` (DHCP, STATIC) | Controls visibility of IPv4 fields |
| Ta5d6ff`ipv4_config.ip` | IPv4 | Regex: Ta5d6ff`\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}` | Visible when Ta5d6ff`address_mode = STATIC` |
| Ta5d6ff`ipv4_config.gateway` | IPv4 | Same regex | Visible when Ta5d6ff`address_mode = STATIC` |
| Ta5d6ff`ipv4_config.subnet` | IPv4 | Same regex | Visible when Ta5d6ff`address_mode = STATIC` |
| Ta5d6ff`ipv4_config.dns` | IPv4 | Same regex | Visible when Ta5d6ff`address_mode = STATIC` |
Tc9d1d9### Display (`Config.DisplayConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`screen_on_secs` | Interval | Dropdown: Ta5d6ff`DISPLAY_SCREEN_ON` intervals | 15s β Always On |
| Ta5d6ff`auto_screen_carousel_secs` | Interval | Dropdown: Ta5d6ff`DISPLAY_CAROUSEL` intervals | 0 (disabled) β 15 min |
| Ta5d6ff`compass_north_top` | Boolean | Toggle | β |
| Ta5d6ff`use_12h_clock` | Boolean | Toggle | β |
| Ta5d6ff`heading_bold` | Boolean | Toggle | β |
| Ta5d6ff`units` | Enum | Dropdown: Ta5d6ff`DisplayUnits` entries | Metric / Imperial |
| Ta5d6ff`wake_on_tap_or_motion` | Boolean | Toggle | β |
| Ta5d6ff`flip_screen` | Boolean | Toggle | β |
| Ta5d6ff`displaymode` | Enum | Dropdown: Ta5d6ff`DisplayMode` entries | β |
| Ta5d6ff`oled` | Enum | Dropdown: Ta5d6ff`OledType` entries | β |
| Ta5d6ff`compass_orientation` | Enum | Dropdown: Ta5d6ff`CompassOrientation` entries | β |
Tc9d1d9### LoRa (`Config.LoRaConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`region` | Enum | Dropdown: Ta5d6ff`RegionInfo` entries | Regional frequency plans |
| Ta5d6ff`use_preset` | Boolean | Toggle | Controls manual vs preset LoRa settings visibility |
| Ta5d6ff`modem_preset` | Enum | Dropdown: Ta5d6ff`ChannelOption` entries | Visible only when Ta5d6ff`use_preset = true` |
| Ta5d6ff`bandwidth` | Integer | Numeric input outside Ta5d6ff`LORA_24`; region/target-aware dropdown in Ta5d6ff`LORA_24` | Visible only when Ta5d6ff`use_preset = false`; protobuf default Ta5d6ff`0` is shown as the firmware's 812.5 kHz Ta5d6ff`LORA_24` default, while unsupported nonzero values remain visible and block Save until replaced |
| Ta5d6ff`spread_factor` | Integer | Numeric input | Visible only when Ta5d6ff`use_preset = false` |
| Ta5d6ff`coding_rate` | Integer | Numeric input | Visible only when Ta5d6ff`use_preset = false` |
| Ta5d6ff`hop_limit` | Integer | Dropdown: 0β7 | β |
| Ta5d6ff`channel_num` | Integer | Numeric input; must be β€ Ta5d6ff`numChannels` | β |
| Ta5d6ff`tx_enabled` | Boolean | Toggle | β |
| Ta5d6ff`tx_power` | Integer | Signed integer input (dBm) | β |
| Ta5d6ff`override_duty_cycle` | Boolean | Toggle | β |
| Ta5d6ff`override_frequency` | Float | MHz value | β |
| Ta5d6ff`sx126x_rx_boosted_gain` | Boolean | Toggle | β |
| Ta5d6ff`ignore_mqtt` | Boolean | Toggle | β |
| Ta5d6ff`config_ok_to_mqtt` | Boolean | Toggle | β |
| Ta5d6ff`pa_fan_disabled` | Boolean | Toggle | Visible only when device Ta5d6ff`hasPaFan = true` |
Tc9d1d9### Bluetooth (`Config.BluetoothConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`enabled` | Boolean | Toggle | β |
| Ta5d6ff`mode` | Enum | Dropdown: Ta5d6ff`PairingMode` entries (excl. UNRECOGNIZED) | β |
| Ta5d6ff`fixed_pin` | String | Exactly 6 digits | β |
Tc9d1d9### Security (`Config.SecurityConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`public_key` | Base64 | 32 bytes; read-only | Auto-derived from private key |
| Ta5d6ff`private_key` | Base64 | 32 bytes | Key generation applies bit masking: Ta5d6ff`f[0] &= 0xF8`, Ta5d6ff`f[31] = (f[31] & 0x7F) Η 0x40` |
| Ta5d6ff`admin_key` | Base64 list | maxCount: 3; each entry 32 bytes | β |
| Ta5d6ff`serial_enabled` | Boolean | Toggle | β |
| Ta5d6ff`debug_log_api_enabled` | Boolean | Toggle | β |
| Ta5d6ff`admin_channel_enabled` | Boolean | Toggle | β |
| Ta5d6ff`is_managed` | Boolean | Toggle | Enabled only when Ta5d6ff`admin_key` list is non-empty |
---
Tc9d1d9## Module Config Screens
Tc9d1d9### MQTT (`ModuleConfig.MQTTConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`enabled` | Boolean | Toggle | β |
| Ta5d6ff`address` | String | maxSize: 63 bytes (proto max_size: 64) | Non-blank required for connection test |
| Ta5d6ff`username` | String | maxSize: 63 bytes (proto max_size: 64) | β |
| Ta5d6ff`password` | Password | maxSize: 63 bytes (proto max_size: 64) | β |
| Ta5d6ff`encryption_enabled` | Boolean | Toggle | β |
| Ta5d6ff`json_enabled` | Boolean | Toggle | β |
| Ta5d6ff`tls_enabled` | Boolean | Toggle | Auto-enforced when using default server with proxy |
| Ta5d6ff`root` | String | maxSize: 31 bytes (proto max_size: 32) | MQTT root topic |
| Ta5d6ff`proxy_to_client_enabled` | Boolean | Toggle | β |
| Ta5d6ff`map_reporting_enabled` | Boolean | Toggle | Controls visibility of map report fields |
| Ta5d6ff`map_report_settings.publish_interval_secs` | Integer | Minimum: 3600 seconds (1 hour) | β |
| Ta5d6ff`map_report_settings.position_precision` | Integer | Slider: 12β15 bits | β |
Tc9d1d9### Serial (`ModuleConfig.SerialConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`enabled` | Boolean | Toggle | β |
| Ta5d6ff`echo` | Boolean | Toggle | β |
| Ta5d6ff`rxd` | Integer | Numeric input (GPIO) | β |
| Ta5d6ff`txd` | Integer | Numeric input (GPIO) | β |
| Ta5d6ff`baud` | Enum | Dropdown: Ta5d6ff`Serial_Baud` entries | β |
| Ta5d6ff`timeout` | Integer | Numeric input | β |
| Ta5d6ff`mode` | Enum | Dropdown: Ta5d6ff`Serial_Mode` entries | β |
| Ta5d6ff`override_console_serial_port` | Boolean | Toggle | β |
Tc9d1d9### External Notification (`ModuleConfig.ExternalNotificationConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`enabled` | Boolean | Toggle | β |
| Ta5d6ff`alert_message` | Boolean | Toggle | β |
| Ta5d6ff`alert_message_buzzer` | Boolean | Toggle | β |
| Ta5d6ff`alert_message_vibra` | Boolean | Toggle | β |
| Ta5d6ff`alert_bell` | Boolean | Toggle | β |
| Ta5d6ff`alert_bell_buzzer` | Boolean | Toggle | β |
| Ta5d6ff`alert_bell_vibra` | Boolean | Toggle | β |
| Ta5d6ff`output` | Integer | Dropdown: GPIO pins 0β48 | Shows Ta5d6ff`active` field when β 0 |
| Ta5d6ff`active` | Boolean | Toggle | Visible when Ta5d6ff`output β 0` |
| Ta5d6ff`output_buzzer` | Integer | Dropdown: GPIO pins 0β48 | Shows Ta5d6ff`use_pwm` field when β 0 |
| Ta5d6ff`use_pwm` | Boolean | Toggle | Visible when Ta5d6ff`output_buzzer β 0` |
| Ta5d6ff`output_vibra` | Integer | Dropdown: GPIO pins 0β48 | β |
| Ta5d6ff`output_ms` | Interval | Dropdown: Ta5d6ff`OUTPUT` intervals | 0sβ10s |
| Ta5d6ff`nag_timeout` | Interval | Dropdown: Ta5d6ff`NAG_TIMEOUT` intervals | 0sβ60s |
| Ta5d6ff`ringtone` | String | maxSize: 230 bytes | RTTTL format |
| Ta5d6ff`use_i2s_as_buzzer` | Boolean | Toggle | β |
Tc9d1d9### Store & Forward (`ModuleConfig.StoreForwardConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`enabled` | Boolean | Toggle | β |
| Ta5d6ff`heartbeat` | Boolean | Toggle | β |
| Ta5d6ff`records` | Integer | Numeric input | β |
| Ta5d6ff`history_return_max` | Integer | Numeric input | β |
| Ta5d6ff`history_return_window` | Integer | Numeric input (seconds) | β |
| Ta5d6ff`is_server` | Boolean | Toggle | β |
Tc9d1d9### Range Test (`ModuleConfig.RangeTestConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`enabled` | Boolean | Toggle | β |
| Ta5d6ff`sender` | Interval | Dropdown: Ta5d6ff`RANGE_TEST_SENDER` intervals | 0 (disabled) β 1 hour |
| Ta5d6ff`save` | Boolean | Toggle | β |
Tc9d1d9### Telemetry (`ModuleConfig.TelemetryConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`device_telemetry_enabled` | Boolean | Toggle | Visible only when Ta5d6ff`canToggleTelemetryEnabled` capability |
| Ta5d6ff`device_update_interval` | Interval | Dropdown: Ta5d6ff`BROADCAST_SHORT` intervals | 30 min β 72 hours |
| Ta5d6ff`environment_measurement_enabled` | Boolean | Toggle | β |
| Ta5d6ff`environment_update_interval` | Interval | Dropdown: Ta5d6ff`BROADCAST_SHORT` intervals | 30 min β 72 hours |
| Ta5d6ff`environment_screen_enabled` | Boolean | Toggle | β |
| Ta5d6ff`environment_display_fahrenheit` | Boolean | Toggle | β |
| Ta5d6ff`air_quality_enabled` | Boolean | Toggle | β |
| Ta5d6ff`air_quality_interval` | Interval | Dropdown: Ta5d6ff`BROADCAST_SHORT` intervals | 30 min β 72 hours |
| Ta5d6ff`power_measurement_enabled` | Boolean | Toggle | β |
| Ta5d6ff`power_update_interval` | Interval | Dropdown: Ta5d6ff`BROADCAST_SHORT` intervals | 30 min β 72 hours |
| Ta5d6ff`power_screen_enabled` | Boolean | Toggle | β |
Tc9d1d9### Canned Message (`ModuleConfig.CannedMessageConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`enabled` | Boolean | Toggle | β |
| Ta5d6ff`rotary1_enabled` | Boolean | Toggle | β |
| Ta5d6ff`inputbroker_pin_a` | Integer | Numeric input (GPIO) | β |
| Ta5d6ff`inputbroker_pin_b` | Integer | Numeric input (GPIO) | β |
| Ta5d6ff`inputbroker_pin_press` | Integer | Numeric input (GPIO) | β |
| Ta5d6ff`inputbroker_event_press` | Enum | Dropdown: Ta5d6ff`InputEventChar` entries | β |
| Ta5d6ff`inputbroker_event_cw` | Enum | Dropdown: Ta5d6ff`InputEventChar` entries | β |
| Ta5d6ff`inputbroker_event_ccw` | Enum | Dropdown: Ta5d6ff`InputEventChar` entries | β |
| Ta5d6ff`updown1_enabled` | Boolean | Toggle | β |
| Ta5d6ff`allow_input_source` | String | maxSize: 63 bytes (proto max_size: 16; UI intentionally allows more) | β |
| Ta5d6ff`send_bell` | Boolean | Toggle | β |
| Ta5d6ff`messages` | String | maxSize: 200 bytes (proto max_size: 201) | Pipe-delimited canned messages |
Tc9d1d9### Audio (`ModuleConfig.AudioConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`codec2_enabled` | Boolean | Toggle | β |
| Ta5d6ff`ptt_pin` | Integer | Numeric input (GPIO) | β |
| Ta5d6ff`bitrate` | Enum | Dropdown: Ta5d6ff`Audio_Baud` entries | β |
| Ta5d6ff`i2s_ws` | Integer | Numeric input (GPIO) | β |
| Ta5d6ff`i2s_sd` | Integer | Numeric input (GPIO) | β |
| Ta5d6ff`i2s_din` | Integer | Numeric input (GPIO) | β |
| Ta5d6ff`i2s_sck` | Integer | Numeric input (GPIO) | β |
Tc9d1d9### Remote Hardware (`ModuleConfig.RemoteHardwareConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`enabled` | Boolean | Toggle | β |
| Ta5d6ff`allow_undefined_pin_access` | Boolean | Toggle | β |
| Ta5d6ff`available_pins` | Pin list | maxCount: 4 | Each pin: gpio 0β255, name maxSize 14 bytes, type Ta5d6ff`RemoteHardwarePinType` enum |
Tc9d1d9### Neighbor Info (`ModuleConfig.NeighborInfoConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`enabled` | Boolean | Toggle | β |
| Ta5d6ff`update_interval` | Integer | Numeric input (seconds) | β |
| Ta5d6ff`transmit_over_lora` | Boolean | Toggle | β |
Tc9d1d9### Ambient Lighting (`ModuleConfig.AmbientLightingConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`led_state` | Boolean | Toggle | β |
| Ta5d6ff`current` | Integer | Numeric input | β |
| Ta5d6ff`red` | Integer | Numeric input (0β255) | β |
| Ta5d6ff`green` | Integer | Numeric input (0β255) | β |
| Ta5d6ff`blue` | Integer | Numeric input (0β255) | β |
Tc9d1d9### Detection Sensor (`ModuleConfig.DetectionSensorConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`enabled` | Boolean | Toggle | β |
| Ta5d6ff`minimum_broadcast_secs` | Interval | Dropdown: Ta5d6ff`DETECTION_SENSOR_MINIMUM` intervals | 0 (unset) β 72 hours |
| Ta5d6ff`state_broadcast_secs` | Interval | Dropdown: Ta5d6ff`DETECTION_SENSOR_STATE` intervals | 0 (unset) β 72 hours |
| Ta5d6ff`send_bell` | Boolean | Toggle | β |
| Ta5d6ff`name` | String | maxSize: 19 bytes (proto max_size: 20) | β |
| Ta5d6ff`monitor_pin` | Integer | Dropdown: GPIO pins 0β48 | β |
| Ta5d6ff`detection_trigger_type` | Enum | Dropdown: Ta5d6ff`TriggerType` entries | β |
| Ta5d6ff`use_pullup` | Boolean | Toggle | β |
Tc9d1d9### Paxcounter (`ModuleConfig.PaxcounterConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`enabled` | Boolean | Toggle | β |
| Ta5d6ff`paxcounter_update_interval` | Interval | Dropdown: Ta5d6ff`PAX_COUNTER` intervals | 15 min β 72 hours |
| Ta5d6ff`wifi_threshold` | Integer | Signed integer (RSSI dBm) | Default: β80 |
| Ta5d6ff`ble_threshold` | Integer | Signed integer (RSSI dBm) | Default: β80 |
Tc9d1d9### Status Message (`ModuleConfig.StatusMessageConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`node_status` | String | maxSize: 80 bytes | Clearable; requires Ta5d6ff`supportsStatusMessage` capability |
Tc9d1d9### Traffic Management (`ModuleConfig.TrafficManagementConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`enabled` | Boolean | Toggle | Requires Ta5d6ff`supportsTrafficManagementConfig` capability |
| Ta5d6ff`position_dedup_enabled` | Boolean | Toggle | β |
| Ta5d6ff`position_precision_bits` | Integer | Numeric input | β |
| Ta5d6ff`position_min_interval_secs` | Integer | Numeric input (seconds) | β |
| Ta5d6ff`nodeinfo_direct_response` | Boolean | Toggle | β |
| Ta5d6ff`nodeinfo_direct_response_max_hops` | Integer | Numeric input | β |
| Ta5d6ff`rate_limit_enabled` | Boolean | Toggle | β |
| Ta5d6ff`rate_limit_window_secs` | Integer | Numeric input (seconds) | β |
| Ta5d6ff`rate_limit_max_packets` | Integer | Numeric input | β |
| Ta5d6ff`drop_unknown_enabled` | Boolean | Toggle | β |
| Ta5d6ff`unknown_packet_threshold` | Integer | Numeric input | β |
| Ta5d6ff`exhaust_hop_telemetry` | Boolean | Toggle | β |
| Ta5d6ff`exhaust_hop_position` | Boolean | Toggle | β |
| Ta5d6ff`router_preserve_hops` | Boolean | Toggle | β |
Tc9d1d9### TAK (`ModuleConfig.TAKConfig`)
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`team` | Enum | Dropdown with custom colors/labels | Only shown when device role is Ta5d6ff`TAK` or Ta5d6ff`TAK_TRACKER` |
| Ta5d6ff`role` | Enum | Dropdown with custom labels | Only shown when device role is Ta5d6ff`TAK` or Ta5d6ff`TAK_TRACKER` |
Tc9d1d9### Mesh Beacon (`ModuleConfig.MeshBeaconConfig`)
Gated behind the Ta5d6ff`supportsMeshBeacon` capability. There is no Ta5d6ff`AdminMessage.ModuleConfigType`
value for this module, so the editor reads from the connect-time config sync (no per-module
refresh) and writes via Ta5d6ff`AdminMessage.setModuleConfig`. Flag edits are read-modify-write so
Ta5d6ff`FLAG_LEGACY_SPLIT` and any unknown bits survive.
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`flags` (Ta5d6ff`FLAG_LISTEN_ENABLED`) | Boolean | Toggle | Bit flag; listen for beacon invitations |
| Ta5d6ff`flags` (Ta5d6ff`FLAG_BROADCAST_ENABLED`) | Boolean | Toggle | Bit flag; enables interval validation below |
| Ta5d6ff`broadcast_message` | String | maxSize: 100 bytes | β |
| Ta5d6ff`broadcast_interval_secs` | Integer | Must be β₯ 3600 when broadcast enabled | Save is blocked while invalid; not validated when broadcast is off |
| Ta5d6ff`broadcast_offer_channel.name` | String | maxSize: 11 bytes (proto max_size: 12) | Blank name drops the offered channel on save (text-only beacon) |
| Ta5d6ff`broadcast_offer_channel.psk` | Base64 | Must decode as Base64 | Field shows an error while invalid; the value is only committed once it decodes (confirming while invalid reverts to the last valid value) |
| Ta5d6ff`broadcast_offer_region` | Enum | Dropdown: Ta5d6ff`RegionCode` entries | β |
| Ta5d6ff`broadcast_offer_preset` | Enum | Dropdown: Ta5d6ff`ModemPreset` entries | Defaults to Ta5d6ff`LONG_FAST` |
| Ta5d6ff`broadcast_targets` | Target list | Rows added/removed via buttons | Per row: Ta5d6ff`region` dropdown, Ta5d6ff`preset` dropdown, Ta5d6ff`channel_index` signed integer input. Non-empty list supersedes the Ta5d6ff`broadcast_on_*` scalars |
| Ta5d6ff`broadcast_on_region` | Enum | Dropdown: Ta5d6ff`RegionCode` entries | Visible only when Ta5d6ff`broadcast_targets` is empty |
| Ta5d6ff`broadcast_on_preset` | Enum | Dropdown: Ta5d6ff`ModemPreset` entries | Visible only when Ta5d6ff`broadcast_targets` is empty; defaults to Ta5d6ff`LONG_FAST` |
| Ta5d6ff`broadcast_send_as_node` | Integer | Signed integer input | Node number to send as; always visible |
| Ta5d6ff`broadcast_on_channel` | β | Not editable | Preserved verbatim through the save round-trip; superseded by the targets list |
---
Tc9d1d9## Channel Config
Channel editing is handled by Ta5d6ff`EditChannelDialog`.
| Field | Type | Validation | Notes |
|-------|------|------------|-------|
| Ta5d6ff`name` | String | maxSize: 11 bytes | Empty name falls back to modem preset name |
| Ta5d6ff`psk` | ByteString | Must be exactly 0, 16, or 32 bytes | Pre-shared key for encryption |
---
Tc9d1d9## Interval Configurations
Time-based fields use predefined interval sets from Ta5d6ff`IntervalConfiguration`. Each configuration
context restricts the available choices to a specific subset of Ta5d6ff`FixedUpdateIntervals`.
| Configuration | Range | Values (seconds) |
|---------------|-------|------------------|
| Ta5d6ff`ALL` | 0 β 2147483647 | 0, 1, 2, 3, 4, 5, 8, 10, 15, 20, 30, 40, 45, 60, 80, 90, 120, 300, 600, 900, 1800, 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200, 2147483647 |
| Ta5d6ff`BROADCAST_SHORT` | 30 min β 72 hr | 1800, 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
| Ta5d6ff`BROADCAST_MEDIUM` | 1 hr β 72 hr | 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
| Ta5d6ff`BROADCAST_LONG` | 3 hr β 72 hr | 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
| Ta5d6ff`NODE_INFO_BROADCAST` | 0 (unset), 3 hr β 72 hr | 0, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
| Ta5d6ff`NAG_TIMEOUT` | 0 β 60 s | 0, 1, 5, 10, 15, 30, 60 |
| Ta5d6ff`OUTPUT` | 0 β 10 s | 0, 1, 2, 3, 4, 5, 10 |
| Ta5d6ff`PAX_COUNTER` | 15 min β 72 hr | 900, 1800, 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
| Ta5d6ff`POSITION` | 1 s β 1 hr | 1, 2, 5, 10, 15, 20, 30, 45, 60, 120, 300, 600, 900, 1800, 3600 |
| Ta5d6ff`POSITION_BROADCAST` | 0 (unset), 1 min β 72 hr | 0, 60, 90, 300, 900, 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
| Ta5d6ff`GPS_UPDATE` | 0 (unset), 8 s β 24 hr | 0, 8, 20, 40, 60, 80, 120, 300, 600, 900, 1800, 3600, 21600, 43200, 86400 |
| Ta5d6ff`RANGE_TEST_SENDER` | 0 (disabled) β 1 hr | 0, 15, 30, 45, 60, 300, 600, 900, 1800, 3600 |
| Ta5d6ff`SMART_BROADCAST_MINIMUM` | 15 s β 1 hr | 15, 30, 45, 60, 300, 600, 900, 1800, 3600 |
| Ta5d6ff`DETECTION_SENSOR_MINIMUM` | 0 (unset), 15 s β 72 hr | 0, 15, 30, 60, 120, 300, 600, 900, 1800, 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
| Ta5d6ff`DETECTION_SENSOR_STATE` | 0 (unset), 15 min β 72 hr | 0, 900, 1800, 3600, 7200, 10800, 14400, 18000, 21600, 43200, 64800, 86400, 129600, 172800, 259200 |
| Ta5d6ff`DISPLAY_SCREEN_ON` | 15 s β Always On | 15, 30, 60, 300, 600, 900, 1800, 3600, 2147483647 |
| Ta5d6ff`DISPLAY_CAROUSEL` | 0 (disabled) β 15 min | 0, 15, 30, 60, 300, 600, 900 |
Tc9d1d9### Shared Constants
Tff7b72- **GPIO Pins:** 0β48 (inclusive)
Tff7b72- **Hop Limits:** 0β7 (inclusive)
---
Tc9d1d9## UI Component Validation
The reusable Compose components in Ta5d6ff`core/ui/.../component/` provide the actual enforcement
layer. Each component accepts validation parameters and rejects or flags invalid input.
Tc9d1d9### EditTextPreference
Tff7b72- **String mode:** Enforces Ta5d6ff`maxSize` in UTF-8 bytes via Ta5d6ff`encodeToByteArray().size <= maxSize`.
Shows a live byte counter when focused.
Tff7b72- **Int mode:** Validates with Ta5d6ff`toIntOrNull()`; sets error icon on failure.
Tff7b72- **Float mode:** Validates with Ta5d6ff`toFloatOrNull()`.
Tff7b72- **Double mode:** Validates with Ta5d6ff`toDoubleOrNull()`; supports international decimal separators
(Ta5d6ff`.`, Ta5d6ff`,`, Ta5d6ff`Ω«`, Ta5d6ff`γ`, Ta5d6ff`Β·`).
Tc9d1d9### SignedIntegerEditTextPreference
Tff7b72- Validates with Ta5d6ff`toIntOrNull()`; shows error icon on invalid input.
Tc9d1d9### DropDownPreference
Tff7b72- Closed-set selection only β no free-form input.
Tff7b72- Automatically filters Ta5d6ff`UNRECOGNIZED` and deprecated enum entries.
Tc9d1d9### SwitchPreference
Tff7b72- Binary toggle; inherently valid. Disabled state shown at reduced opacity.
Tc9d1d9### SliderPreference
Tff7b72- Discrete steps only; values clamped with Ta5d6ff`coerceIn()` and rounded to the nearest valid index.
Tc9d1d9### EditIPv4Preference
Tff7b72- Regex validation: Ta5d6ff`\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}`.
Tff7b72- Stored as a little-endian Ta5d6ff`Int`; displayed as dotted-decimal.
Tc9d1d9### EditPasswordPreference
Tff7b72- Delegates to Ta5d6ff`EditTextPreference` with Ta5d6ff`maxSize` enforcement and password visibility toggle.
Tc9d1d9### EditBase64Preference
Tff7b72- Validates Base64 encoding on input.
Tff7b72- Flags all-zero 32-byte values as errors (empty/unset key).
Tc9d1d9### BitwisePreference
Tff7b72- Closed checkbox set; toggles individual bit flags via XOR.
Tff7b72- "Clear" button resets to 0.
Tc9d1d9### EditListPreference
Tff7b72- Enforces Ta5d6ff`maxCount` for list length.
Tff7b72- Per-element validation varies by type: Ta5d6ff`Int` range 0β255 for GPIO pins,
Ta5d6ff`ByteString` via Base64 parsing, composite Ta5d6ff`RemoteHardwarePin` with nested field rules.
Tc9d1d9### PositionPrecisionPreference
Tff7b72- State machine with three modes: disabled (0), precision range (10β19), full precision (32).
Tff7b72- Slider constrained to 10β19 with 8 discrete steps.
Tc9d1d9### ConfigState
Tff7b72- Generic wrapper that tracks Ta5d6ff`isDirty` (current value β initial value).
Tff7b72- Changes are only persisted on explicit save; cancel reverts to the initial snapshot.
Served by rngit 1.5.2 - Generated in 0.33s